package com.example.event;

import com.example.entity.Course;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.event.TransactionPhase;
import org.springframework.transaction.event.TransactionalEventListener;

@Service
public class DemoEventService {

    @Autowired
    private ApplicationEventPublisher eventPublisher;

    public void publish(String message) {
        System.out.println("主线程：" + Thread.currentThread().getName());
        eventPublisher.publishEvent(new DemoEvent(1, new Course(1, message)));
        System.out.println("推送 DemoEvent..."); // 竟然是同步的 todo
    }


    @TransactionalEventListener(fallbackExecution = true, phase = TransactionPhase.AFTER_COMMIT)
    public void handleTransactionEvent(DemoEvent<?> event) {
        try {
            Thread.sleep(3_000);
            System.out.println("监听的线程：" + Thread.currentThread().getName());
            doSendEvent(event);
        } catch (Exception e) {
            System.out.println("发送事件失败, event={}" + event + e);
        }
    }

    private void doSendEvent(DemoEvent<?> event) {
        System.out.println("发送 kafka 事件：" + event.getData());
    }

    @EventListener
    public void processUserCreatedEvent(UserCreatedEvent event) {
        // send email
        sendEmail(event.getUserId(), event.getName());
    }

    /**
     * 模拟发送注册成功邮件
     */
    private void sendEmail(Integer userId, String name) {
        System.out.println("============== 发送邮件 ============");
        // 模拟耗时操作
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // 模拟报错, 会影响到原业务逻辑吗？ 答案是：会！
        int i = 10/0;
        System.out.println(String.format("======用户: %s (%s) 邮件发送成功", name, userId));
    }

}
